package net.fltx.assets.controller;

import net.fltx.assets.config.MimeType;
import net.fltx.assets.entity.FileVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.Encoder;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

@Controller
public class IndexController {

    @Value("${storage}")
    String storage;

    @Value("${listShow}")
    boolean listShow;

    @Autowired
    MimeType mimeType;

    @GetMapping({"/","/**"})

    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
        storage=storage.replaceAll("[\\\\/]+^","").replaceAll("[/\\\\]+","/");
        //System.out.println(storage);
        FileVO fileVO = new FileVO();
        try {
            String uri=URLDecoder.decode(request.getRequestURI().replaceAll("\\+","%2B"),"utf-8");
            File file = new File(storage + uri);
            //System.out.println(file);

            if (file.exists()) {
                fileVO.setName(file.getName());
                fileVO.setAbsolutePath(file.getAbsolutePath()
                        .replaceAll("[/\\\\]+","/")
                        .replaceFirst(storage,""));
                String parent=file.getParent();
                if(parent!=null && parent.startsWith(storage)){
                    parent=parent.replaceAll("[/\\\\]+","/");
                    fileVO.setParentPath(parent.replaceAll("[/\\\\]+","/")
                            .replaceFirst(storage,"")
                    );
                }
                fileVO.setIsDirectory(file.isDirectory());
                if (file.isDirectory() && listShow) {
                    ArrayList<FileVO> fileVOS = new ArrayList<>();
                    String[] list = file.list();
                    for (int i = 0; i < list.length; i++) {
                        FileVO fileVO1 = new FileVO();
                        fileVO1.setName(list[i]);
                        fileVO1.setParentPath(fileVO.getAbsolutePath());
                        File f=new File(file.getAbsolutePath()+"/"+fileVO1.getName());
                        fileVO1.setIsDirectory(f.isDirectory());
                        fileVO1.setAbsolutePath(fileVO.getAbsolutePath()+fileVO1.getName());
                        fileVOS.add(fileVO1);
                    }
                    Collections.sort(fileVOS,(f1,f2)->{
                        if(f1.getIsDirectory()==f2.getIsDirectory()) {
                            return f1.getName().compareTo(f2.getName());
                        }else if(f1.getIsDirectory()){
                            return -1;
                        }else {
                            return 1;
                        }

                    });
                    fileVO.setChildren(fileVOS);
                    //System.out.println(Arrays.toString(list));
                    //model.put("fileList", list);
                    //modelAndView.addAllObjects(model);
                    model.addAttribute("file",fileVO);

                    //System.out.println(model);
                    return "index";
                } else if(file.isFile()) {
                    //response.reset();
                    ServletOutputStream outputStream = response.getOutputStream();
                    FileInputStream fileInputStream = new FileInputStream(file);

                    //response.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(file.getName(),"utf-8"));
                    response.addHeader("Content-Length", "" + file.length());
                    response.setContentType(mimeType.get(file.getName()));
                    byte[] bytes=new byte[64*1024];
                    try {
                        while (true) {
                            int read = fileInputStream.read(bytes);
                            if(read<0) break;
                            outputStream.write(bytes,0,read);
                            outputStream.flush();
                            Thread.yield();
                        };
                    }catch (Exception e){
                        e.printStackTrace();
                        response.setStatus(500);
                        return "500";
                    }finally {
                        fileInputStream.close();
                    }
                    return null;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.setStatus(500);
            return "500";
        }
        response.setStatus(404);
        return "404";
    }

}
